package org.raymond.iworks.study.basic.thread.phaser;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.Phaser;

@Slf4j
public class Demo4 {
    static final Random random = new Random();
    public static void main(String[] args) {
        test1();
    }

    public static void test1(){
        Phaser phaser = new Phaser(){
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                int staffs = registeredParties - 1;
                switch (phase) {
                    case 0:
                        log.info("大家都到公司了,出发去公园,人数:" + staffs);
                        break;
                    case 1:
                        log.info("大家都到公园门口了,出发去餐厅,人数:" + staffs);
                        break;
                    case 2:
                        log.info("大家都到餐厅了,开始用餐,人数:" + staffs);
                        break;
                }
                // 判断是否只剩下主线程（一个参与者），如果是，则返回true，代表终止
                return registeredParties == 1;
            }
        };

        // 注册主线程 ———— 让主线程全程参与
        phaser.register();
        final StaffTask staffTask = new StaffTask();

        // 3个全程参与TB的员工
        for (int i = 0; i < 3; i++) {
            // 添加任务数
            phaser.register();
            new Thread(() -> {
                try {
                    staffTask.phase0();
                    phaser.arriveAndAwaitAdvance();

                    staffTask.phase1();
                    phaser.arriveAndAwaitAdvance();

                    staffTask.phase2();
                    phaser.arriveAndAwaitAdvance();

                    staffTask.phase3();
                    // 完成了，注销离开
                    phaser.arriveAndDeregister();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        // 两个不聚餐的员工加入又离开
        for (int i = 0; i < 2; i++) {
            phaser.register();
            new Thread(() -> {
                try {
                    staffTask.phase0();
                    phaser.arriveAndAwaitAdvance();

                    staffTask.phase1();
                    log.info("员工【" + Thread.currentThread().getName() + "】回家了");
                    // 完成了，注销离开
                    phaser.arriveAndDeregister();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        while (!phaser.isTerminated()) {
            int phase = phaser.arriveAndAwaitAdvance();
            if (phase == 2) {
                // 到了去餐厅的阶段，又新增4人，参加晚上的聚餐
                for (int i = 0; i < 4; i++) {
                    phaser.register();
                    new Thread(() -> {
                        try {
                            staffTask.phase2();
                            phaser.arriveAndAwaitAdvance();
                            staffTask.phase3();
                            // 完成了，注销离开
                            phaser.arriveAndDeregister();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }).start();
                }
            }
        }
    }

    static public class StaffTask {
        public void phase0() throws InterruptedException {
            String staff = Thread.currentThread().getName();
            log.info(staff + "从家出发了……");
            Thread.sleep(random.nextInt(5000));
            log.info(staff + "到达公司");
        }

        public void phase1() throws InterruptedException {
            String staff = "员工【" + Thread.currentThread().getName() + "】";
            log.info(staff + "出发去公园玩");
            Thread.sleep(random.nextInt(5000));
            log.info(staff + "到达公园门口集合");
        }
        public void phase2() throws InterruptedException {
            String staff = "员工【" + Thread.currentThread().getName() + "】";
            log.info(staff + "出发去餐厅");
            Thread.sleep(random.nextInt(5000));
            log.info(staff + "到达餐厅");
        }
        public void phase3() throws InterruptedException {
            String staff = "员工【" + Thread.currentThread().getName() + "】";
            log.info(staff + "开始用餐");
            Thread.sleep(random.nextInt(5000));
            log.info(staff + "用餐结束，回家");
        }
    }
}
